package thread;

import java.util.concurrent.*;
import java.util.*;
import java.text.*;

public class CyclicBarrierTest {
	
	 Vector v;
	
	private static final int MAX_THREADS = 5;

	public static void main(String[] args) {
		
		CyclicBarrier cyclicBarrier = new CyclicBarrier(MAX_THREADS,
				new Runnable() {
					private int count = 1;
					public void run() {
						System.out.printf("\n ******* CYCLIC BARRIER FINISHED %d TIME ******** \n\n",count++);
					}
				});

		System.out.println("Starting Threads creating");
		for (int i = 0; i < MAX_THREADS; i++) {
			Thread t = new Thread(new WorkerThread(cyclicBarrier, String.format("Thread-%d", i)));
			t.start();
		}
		System.out.println(" Finished thread creation \n");
	}

	private static class WorkerThread implements Runnable {
		
		private CyclicBarrier cyclicBarrier;

		private String name;

		public WorkerThread(CyclicBarrier cyclicBarrier, String name) {
			this.name = name;
			this.cyclicBarrier = cyclicBarrier;
		}

		public void run() {
			
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
				
				System.out.printf("%s : Doing Step 1 Work on %s\n", name, getFormattedDate(sdf));
				Thread.sleep(getRandomWaitTime());
				System.out.printf("%s : Finished Step 1 work on %s\n", name, getFormattedDate(sdf));
				
				int count = cyclicBarrier.await();
				// Await returns an int which is the arrival index 1 means first 0 means last
				System.out.printf("  Cyclic Barrier count end of Step 1 Batch of work on %s is %d\n", name, count);				
				if (count == 0) {
					System.out.printf(" RE-SET CYCLIC BARRIER  \n");
					cyclicBarrier.reset();
				}		
				
				// cyclicBarrier.reset();
				
				System.out.printf("%s : Doing Step 2 Batch of Work on %s\n", name , getFormattedDate(sdf));
				Thread.sleep(getRandomWaitTime());				
				System.out.printf("%s : Finished Step 2 Batch of work on %s\n", name , getFormattedDate(sdf));
				
				count = cyclicBarrier.await();
				System.out.printf("%s : Cyclic Barrier count end of Step 2 Batch of work on is %d\n", name, count);
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}

		private String getFormattedDate(SimpleDateFormat sdf) {
			return sdf.format(new Date());
		}

		private int getRandomWaitTime() {
			return (int) ((Math.random() + 1) * 1000);
		}

	}
	
}
